package strangeattractor.UI;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import strangeattractor.core.Renderer;
import strangeattractor.core.Transformer;

public abstract class EquationModifier extends JPanel implements Renderer {
	//EquationModifier is the basic 'skeleton' for the user interface.
	//All common elements are handled through this object.

	protected ImageRenderer center = null;
	public int progress = 0;
	public int pMax = 50;

	private JProgressBar progressBar = new JProgressBar();

	public EquationModifier() {
		super();
		initialize();
	}

	protected void initialize() {

		this.setSize(new Dimension(1000, 750));
		this.setLayout(new BorderLayout());
		center = new ImageRenderer(new Dimension(640, 480),
				initializeEquation(), this);
		center.addComponentListener(new ComponentListener(){

			@Override
			public void componentHidden(ComponentEvent e) {}

			@Override
			public void componentMoved(ComponentEvent e) {
				center.preview(center.getSize());
			}

			@Override
			public void componentResized(ComponentEvent e) {
				center.preview(center.getSize());
			}

			@Override
			public void componentShown(ComponentEvent e) {
				center.preview(center.getSize());
			}
			
		});
		center.addMouseListener(new MouseListener() {

			private Point referencePoint = new Point(0, 0);

			@Override
			public void mouseClicked(MouseEvent arg0) {
				center.preview(center.getSize());

			}

			@Override
			public void mouseEntered(MouseEvent arg0) {
			}

			@Override
			public void mouseExited(MouseEvent arg0) {
			}

			@Override
			public void mousePressed(MouseEvent arg0) {
				referencePoint = arg0.getLocationOnScreen();

			}

			@Override
			public void mouseReleased(MouseEvent arg0) {
				double deltaX = referencePoint.x - arg0.getLocationOnScreen().x;
				double deltaY = referencePoint.y - arg0.getLocationOnScreen().y;
				if (arg0.getButton() == MouseEvent.BUTTON1) {
					center.gen.rotate(deltaX / 200, deltaY / 200);
					center.preview(center.getSize());
				}
				if (arg0.getButton() == MouseEvent.BUTTON2) {
					if (arg0.isControlDown()) {
						center.gen.zoom(-Math.sqrt(deltaX * deltaX + deltaY
								* deltaY) / 10);
					} else
						center.gen.zoom(Math.sqrt(deltaX * deltaX + deltaY
								* deltaY) / 10);
					center.preview(center.getSize());
				}
				if (arg0.getButton() == MouseEvent.BUTTON3) {
					center.gen.translate((int) deltaX, (int) deltaY);
					center.preview(center.getSize());
				}
			}

		});
		this.add(center, BorderLayout.CENTER);
		JPanel equationModifierPanel = new JPanel();
		FlowLayout layout = new FlowLayout();
		layout.setAlignment(SwingConstants.VERTICAL);
		JLabel labelA = new JLabel("Variables:");
		equationModifierPanel.add(labelA);
		this.fill(equationModifierPanel);
		this.initializerRenderTools(equationModifierPanel);
		this.add(equationModifierPanel, BorderLayout.SOUTH);
		equationModifierPanel.setLayout(layout);
		this.center.preview(center.getSize());
	}

	private void initializerRenderTools(JPanel equationModifierPanel) {

		final JSlider qualitySlider = new JSlider(SwingConstants.VERTICAL,
				100000, 200000000, 20000000);
		qualitySlider.setMajorTickSpacing(20000000);
		qualitySlider.setMinorTickSpacing(10000000);
		qualitySlider.setPaintTicks(true);
		qualitySlider.setToolTipText("Render Quality");

		final JSlider sampleSlider = new JSlider(SwingConstants.VERTICAL, 1,
				1000, 50);
		sampleSlider.setMajorTickSpacing(250);
		sampleSlider.setMinorTickSpacing(50);
		sampleSlider.setPaintTicks(true);
		sampleSlider.setToolTipText("Sample Size");
		sampleSlider.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent arg0) {
				pMax = sampleSlider.getValue();
			}

		});

		final JSlider exposureSlider = new JSlider(SwingConstants.VERTICAL, 1,
				1000, 100);
		exposureSlider.setMajorTickSpacing(250);
		exposureSlider.setMinorTickSpacing(50);
		exposureSlider.setPaintTicks(true);
		exposureSlider.setToolTipText("Exposure");

		final JSlider gammaSlider = new JSlider(SwingConstants.VERTICAL, 50,
				200, 50);
		gammaSlider.setMajorTickSpacing(50);
		gammaSlider.setMinorTickSpacing(10);
		gammaSlider.setPaintTicks(true);
		gammaSlider.setToolTipText("Gamma");

		JButton renderButton = new JButton("Render!");
		renderButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				progressBar.setValue(0);
				progress = 0;
				center.render(center.getSize(), qualitySlider.getValue(),
						sampleSlider.getValue(), exposureSlider.getValue(),
						(double) (gammaSlider.getValue()) / 100.0);
			}

		});

		JButton renderCancelButton = new JButton("Cancel Render");
		renderCancelButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				center.cancel();
			}

		});

		equationModifierPanel.add(renderButton);
		equationModifierPanel.add(renderCancelButton);
		equationModifierPanel.add(qualitySlider);
		equationModifierPanel.add(sampleSlider);
		equationModifierPanel.add(exposureSlider);
		equationModifierPanel.add(gammaSlider);
		equationModifierPanel.add(progressBar);
	}

	public void display(Image i) {
			progressBar.setMaximum(pMax);
			progress++;
			progressBar.setValue(progress);
			if (pMax == progress) {
				progressBar.setForeground(Color.green);
			} else
				progressBar.setForeground(Color.blue);
	}

	protected abstract Transformer initializeEquation();

	// This method sets up all the sliders
	// for all the equation variables
	protected abstract void fill(JPanel sliders);

}
